package com.kayb.patterns.structural;

/**
 * 桥接模式，将抽象与具体实现分开，从而满足各自的不同演化，比如<code>java.sql.DriverManager</code>
 * 场景：一个类存在两个（或多个）独立变化的维度，且这两个（或多个）维度都需要独立进行扩展。
 * @author huangkaibin
 * @date 2018-08-28
 **/
public class Bridge {
    interface Enchantment {
        void onActivate();
        void apply();
        void onDeactivate();
    }

    interface Weapon {
        void wield();
        void swing();
        void unwield();
        Enchantment getEnchantment();
    }

    static abstract class AbstractWeapon implements Weapon {
        protected Enchantment enchantment;

        public AbstractWeapon(Enchantment enchantment) {
            this.enchantment = enchantment;
        }

        @Override
        public Enchantment getEnchantment() {
            return enchantment;
        }
    }

    static class Sword extends AbstractWeapon {

        public Sword(Enchantment enchantment) {
            super(enchantment);
        }

        @Override
        public void wield() {
            enchantment.onActivate();
            System.out.println("The sword is wielded.");
        }

        @Override
        public void swing() {
            enchantment.apply();
            System.out.println("The sword is swinged.");
        }

        @Override
        public void unwield() {
            enchantment.onDeactivate();
            System.out.println("The sword is unwielded.");
        }
    }

    static class Hammer extends AbstractWeapon {

        public Hammer(Enchantment enchantment) {
            super(enchantment);
        }

        @Override
        public void wield() {
            enchantment.onActivate();
            System.out.println("The hammer is wielded.");
        }

        @Override
        public void swing() {
            enchantment.apply();
            System.out.println("The hammer is swinged.");
        }

        @Override
        public void unwield() {
            enchantment.onDeactivate();
            System.out.println("The hammer is unwielded.");
        }
    }

    static class FlyingEnchantment implements Enchantment {

        @Override
        public void onActivate() {
            System.out.println("The item begins to glow faintly.");
        }

        @Override
        public void apply() {
            System.out.println("The item flies and strikes the enemies finally returning to owner's hand.");
        }

        @Override
        public void onDeactivate() {
            System.out.println("The item's glow fades.");
        }
    }

    static class SoulEatingEnchantment implements Enchantment {

        @Override
        public void onActivate() {
            System.out.println("The item spreads bloodlust.");
        }

        @Override
        public void apply() {
            System.out.println("The item eats the soul of enemies.");
        }

        @Override
        public void onDeactivate() {
            System.out.println("Bloodlust slowly disappears.");
        }
    }

    public static void main(String[] args) {
        Sword enchantedSword = new Sword(new SoulEatingEnchantment());
        enchantedSword.wield();
        enchantedSword.swing();
        enchantedSword.unwield();
        // The sword is wielded.
        // The item spreads bloodlust.
        // The sword is swinged.
        // The item eats the soul of enemies.
        // The sword is unwielded.
        // Bloodlust slowly disappears.

        Hammer hammer = new Hammer(new FlyingEnchantment());
        hammer.wield();
        hammer.swing();
        hammer.unwield();
        // The hammer is wielded.
        // The item begins to glow faintly.
        // The hammer is swinged.
        // The item flies and strikes the enemies finally returning to owner's hand.
        // The hammer is unwielded.
        // The item's glow fades.
    }

}
